<?php
namespace x\db\driver;
use x\G;

class Base {
	public $mysqli;
	public $debug;
	public $logData = [];
	//开始事务
	public function begin() {
		$this->mysqli->autocommit(false);
		$this->mysqli->begin_transaction();
	}

	//执行事务
	public function end($arr) {
		$check = true;
		foreach ($arr as $v) {
			if (!$v) {
				$check = false;
				break;
			}
		}
		if ($check) {
			$this->mysqli->commit();
		} else {
			$this->mysqli->rollback();
		}
		$this->mysqli->autocommit(true);
		return $check;
	}

	//缓存sql
	public function cache($sql, $vars = [], $limit = '') {
		return $this->query($sql, $vars, $limit, false, true);
	}

	/**
	 * 执行sql语句
	 * @param  [type]  $sql     [sql语句]
	 * @param  array   $vars    [参数]
	 * @param  string  $limit   [取多前少条]
	 * @param  boolean $isCount [是否统计总条数, 用于分页]
	 * @param  boolean $isCache [是否缓存,  todo]
	 * @return [type]           [按sql类型返回数据]
	 */
	public function query($sql, $vars = [], $limit = '', $isCount = false, $isCache = false, $islower = true) {
		$sql = str_replace(PHP_EOL, " ", $sql);
		$limit = (int) $limit;
		$sql = trim($sql);
		if ($islower) {
			$sql = strtolower($sql);
		}
		$temp_sql = $this->logSql($sql, $vars);

		#分情况
		$arr = explode(" ", $sql);
		$type = trim(strtolower($arr[0]));
		switch ($type) {
		case 'select':
			if ($isCount) {
				$sql = "select SQL_CALC_FOUND_ROWS " . ltrim(ltrim($sql, 'select'), 'SELECT');
			} else {
				if ($isCache) {
					//todo: 缓存, 暂时不做
				}
			}
			$stmt = $this->mysqli->prepare($sql);
			if (!$stmt && $this->debug) {
				e("预编译sql错误:" . $temp_sql);
			}
			if ($vars) {
				call_user_func_array([$stmt, 'bind_param'], $this->_bind_param($vars));
			}

			$stmt->execute();
			if ($stmt->error && $this->debug) {
				e($temp_sql . ' : ' . $stmt->error);
			}
			$rs = [];
			$row = [];
			$params = [];
			#找出所有字段名称
			$meta = $stmt->result_metadata();
			while ($field = $meta->fetch_field()) {
				$params[] = &$row[$field->name];
			}
			#绑定所有字段
			call_user_func_array(array($stmt, 'bind_result'), $params);
			$i = 0;
			while ($stmt->fetch()) {
				$rs[$i] = array();
				foreach ($row as $k => $v) {
					$rs[$i][$k] = $v;
				}

				$i++;
			}
			//取前多少条
			if ($limit === 1 && isset($rs[0])) {
				$rs = $rs[0];
			} else if ($limit) {
				$limit = $limit < count($rs) ? $limit : count($rs);
				$temp = [];
				for ($i = 0; $i < $limit; $i++) {
					$temp[] = $rs[$i];
				}
				$rs = $temp;
			} else {
				//获取条数, 用于分页
				if ($isCount) {
					$stmt = $this->mysqli->query('SELECT FOUND_ROWS()');
					$totalCount = $stmt->fetch_row();
					$rs = [
						$rs,
						isset($totalCount[0]) ? $totalCount[0] : 0,
					];
				}
			}
			$stmt->close();
			break;
		case 'update':
			$stmt = $this->mysqli->prepare($sql);
			if (!$stmt && $this->debug) {
				e("预编译sql错误:" . $temp_sql);
			}
			if ($vars) {
				call_user_func_array([$stmt, 'bind_param'], $this->_bind_param($vars));
			}

			$stmt->execute();
			if ($stmt->error && $this->debug) {
				e($temp_sql . ' : ' . $stmt->error);
			}
			$rs = $stmt->affected_rows;
			$stmt->close();
			break;
		case 'delete':
			$stmt = $this->mysqli->prepare($sql);
			if (!$stmt && $this->debug) {
				e("预编译sql错误:" . $temp_sql);
			}
			if ($vars) {
				call_user_func_array([$stmt, 'bind_param'], $this->_bind_param($vars));
			}

			$stmt->execute();
			if ($stmt->error && $this->debug) {
				e($temp_sql . ' : ' . $stmt->error);
			}
			$rs = $stmt->affected_rows;
			$stmt->close();
			break;
		case 'insert':
			$stmt = $this->mysqli->prepare($sql);
			if (!$stmt && $this->debug) {
				e("预编译sql错误:" . $temp_sql);
			}
			if ($vars) {
				call_user_func_array([$stmt, 'bind_param'], $this->_bind_param($vars));
			}

			$stmt->execute();
			if ($stmt->error && $this->debug) {
				e($temp_sql . ' : ' . $stmt->error);
			}
			$rs = $stmt->insert_id;
			$stmt->close();
			break;
		default:
			$stmt = $this->mysqli->prepare($sql);
			if (!$stmt && $this->debug) {
				e("预编译sql错误:" . $temp_sql);
			}
			if ($vars) {
				call_user_func_array([$stmt, 'bind_param'], $this->_bind_param($vars));
			}

			$stmt->execute();
			if ($stmt->error && $this->debug) {
				e($temp_sql . ' : ' . $stmt->error);
			}
			$rs = $stmt->affected_rows;
			$stmt->close();
			break;
			// e('sql 错误');
			// break;
		}
		return $rs;
	}
	/**
	 * 格式化参数绑定
	 * @param  [type] $vars [description]
	 * @return [type]       [description]
	 */
	private function _bind_param($vars) {
		$temp = [''];
		foreach ($vars as $v) {
			$type = '';
			switch (gettype($v)) {
			case 'NULL':
			case 'string':
				$type = 's';
				break;
			case 'boolean':
			case 'integer':
				$type = 'i';
				break;
			case 'blob':
				$type = 'b';
				break;
			case 'double':
				$type = 'd';
				break;
			}
			$temp[0] .= $type;
			array_push($temp, $v);
		}
		$refs = [];
		foreach ($temp as $key => $value) {
			$refs[$key] = &$temp[$key];
		}
		return $refs;
	}
	//查找单条数据
	public function find($table, $id = '', $fields = '*') {
		$sql = "select {$fields} from `{$table}` WHERE id = ?";
		$vars = [(int) $id];
		return $this->query($sql, $vars, 1);
	}
	/**
	 * 查找数据,二维
	 * @param  [type] $table  [表名称]
	 * @param  string $where  [查找条件]
	 * $where 格式:  ['sex=? and name=?', [1, '张三']]
	 * @param  string $fields [查找字段]
	 * @return [type]         [description]
	 */
	public function select($table, $where = [], $fields = '*') {
		$sql = "select {$fields} from `{$table}` ";
		if ($where) {
			$sql .= ' where ' . $where[0];
		}
		return $this->query($sql, $where[1]);
	}
	/**
	 * 更新表,
	 * @param  [type] $table [表名称]
	 * @param  [type] $data  [更新数组,键值对]
	 * @param  array  $where [更新条件]
	 * $where 格式:  ['sex=? and name=?', [1, '张三']]
	 * @return [type]        [description]
	 */
	public function update($table, $data, $where = []) {
		$temp = [];
		$vars = [];
		foreach ($data as $k => $v) {
			if ($k == 'id') {
				continue;
			}

			$vars[] = $v;
			array_push($temp, "`$k`=?");
		}
		if (!$temp) {
			e('缺少更新内容');
		}

		$sql = "update `{$table}` set " . implode(',', $temp);
		#id作为更新条件
		if (isset($data['id']) && !$where) {
			$sql .= " where id=" . (int) $data['id'];
		} else {
			if ($where) {
				$sql .= ' where ' . $where[0];
				$vars = array_merge($vars, $where[1]);
			} else {
				exit('update快捷方式不能缺少条件');
			}
		}
		return $this->query($sql, $vars);
	}
	//插入
	public function insert($table, $data) {
		$keys = [];
		$vars = [];
		foreach ($data as $k => $v) {
			$keys[] = $k;
			$vars[] = $v;
		}
		$sql = "insert into `{$table}` (`" . implode('`,`', $keys) . "`) values (" . countZwf($vars) . ")";
		return $this->query($sql, $vars);
	}
	//插入多条
	public function insertAll($table, $data) {
		$db_val = '';
		$vars = [];
		foreach ($data as $k => $v) {
			$keys = [];
			$db_val .= "(";
			foreach ($v as $key => $val) {
				$keys[] = "`{$key}`";
				$vars[] = $val;
				$db_val .= "?,";
			}
			$db_val = rtrim($db_val, ",");
			$db_val .= "),";
		}
		$db_val = rtrim($db_val, ",");
		$sql = "insert into `{$table}` (" . implode(',', $keys) . ") values " . $db_val;
		return $this->query($sql, $vars);
	}
	//删除
	public function delete($table, $val = '', $fields = 'id') {
		$sql = "delete from `{$table}` WHERE `$fields`=?";
		$vars = [$val];
		return $this->query($sql, $vars);
	}

	//组装占位符
	public function logSql($sql, $vars) {
		$t = md5(time());
		$sql = str_replace("?", $t, $sql);
		foreach ($vars as $v) {
			if (is_string($v)) {
				$sql = preg_replace("/$t/", "'{$v}'", $sql, 1);
			} else {
				$sql = preg_replace("/$t/", "{$v}", $sql, 1);
			}
		}
		$this->logData[] = $sql;
		return $sql;
	}
	//显示sql
	public function getSql() {
		t($this->logData);
	}
	public function close() {
		@$this->mysqli->close();
	}
	public function __destruct() {
		$this->close();
	}
	public function __clone() {
		e('Clone is not allow!');
	}
}
